module interrupt_controller (
    input  wire         sys_clk,        // 外部中断控制器时钟
    input  wire         sys_resetn,     // 外部中断控制器复位，低有效
    input  wire         cpu_clk,        // 处理器核时钟
    input  wire         cpu_resetn,     // 处理器核复位，低有效
    input  wire [31:0]  int_en,         // 中断使能
    input  wire [31:0]  int_edge,       // 边沿/电平触发选择
    input  wire [31:0]  int_pol,        // 极性选择
    input  wire [31:0]  int_in,         // 来自设备的32位中断输入
    input  wire [31:0]  int_clr,        // 清除中断（针对边沿触发）
    output wire [31:0]  int_state,      // 当前各通道中断状态
    output wire         int_out         // 输出给处理器核的总中断信号
);

    // 保存上一个周期的输入信号用于边沿检测
/*     reg [31:0] int_in_d;
    always @(posedge sys_clk or negedge sys_resetn) begin
        if (!sys_resetn)
            int_in_d <= 32'b0;
        else
            int_in_d <= int_in;
    end */
	
	//由于测试文件的设计设计问题，会出现时钟边沿信号变化的问题，加入两级打拍来解决
	reg [31:0] int_in_d, int_in_m;
	always @(posedge sys_clk or negedge sys_resetn) begin
		if (!sys_resetn) begin
			int_in_d  <= 32'b0;
			int_in_m <= 32'b0;
		end else begin
			int_in_m  <= int_in;
			int_in_d <= int_in_m;
		end
	end

    // 边沿检测
    wire [31:0] rise_edge, fall_edge;
    assign rise_edge = ~int_in_d & int_in; // 上升沿
    assign fall_edge = int_in_d & ~int_in; // 下降沿

    // 中断有效状态寄存器（仅边沿触发时需要记忆，电平触发直接读输入）
    reg [31:0] edge_irq_flag;

    integer i;
    always @(posedge sys_clk or negedge sys_resetn) begin
        if (!sys_resetn)
            edge_irq_flag <= 32'b0;
        else begin
            for (i = 0; i < 32; i = i + 1) begin
                if (int_edge[i]) begin // 边沿触发
                    // 边沿检测 & 使能
                    if (int_en[i] && (
                        ( int_pol[i] && rise_edge[i]) || // 上升沿
                        (~int_pol[i] && fall_edge[i])    // 下降沿
                    ))
                        edge_irq_flag[i] <= 1'b1;
                    // 清除
                    else if (int_clr[i])
                        edge_irq_flag[i] <= 1'b0;
                end else begin
                    edge_irq_flag[i] <= 1'b0; // 电平触发不用记忆
                end
            end
        end
    end

    // 组合电平触发判断
    wire [31:0] level_irq_flag;
    assign level_irq_flag = (int_pol & int_in) | (~int_pol & ~int_in);

    // 总的IRQ有效位
    wire [31:0] irq_valid;
    assign irq_valid = (int_edge & edge_irq_flag) | (~int_edge & level_irq_flag);

    // 输出状态（加使能控制）
    assign int_state = irq_valid & int_en;

    // 跨时钟域同步：sys_clk域int_state同步到cpu_clk域
    reg [31:0] int_state_sys;
    always @(posedge sys_clk or negedge sys_resetn) begin
        if (!sys_resetn)
            int_state_sys <= 32'b0;
        else
            int_state_sys <= int_state;
    end

    // 两级同步到cpu_clk域
    reg [31:0] int_state_cpu1, int_state_cpu2;
    always @(posedge cpu_clk or negedge cpu_resetn) begin
        if (!cpu_resetn) begin
            int_state_cpu1 <= 32'b0;
            int_state_cpu2 <= 32'b0;
        end else begin
            int_state_cpu1 <= int_state_sys;
            int_state_cpu2 <= int_state_cpu1;
        end
    end

    // int_out为cpu_clk域下所有有效中断的"或"
    assign int_out = |int_state_cpu2;

endmodule